package com.transer.utils;

import java.util.ArrayList;
import java.util.concurrent.ConcurrentLinkedQueue;

import org.apache.log4j.Logger;

public class JobQueueOB implements Runnable {

	private static final Logger logger = Logger.getLogger(JobQueueOB.class);
	private static JobQueueOB instance;

	public static int JOB_QUEUE_SIZE = 4;
	public static int JOB_QUEUE_BLOCK_STATE = 10;

	private boolean isRunning;

	private ArrayList<JobQueue> jobQueueGroup = new ArrayList<JobQueue>();

	public static JobQueueOB getInstance() {
		if (instance == null) {
			instance = new JobQueueOB(JOB_QUEUE_SIZE);
		}
		return instance;
	}

	private JobQueueOB() {

	}

	private JobQueueOB(int size) {
		jobQueueGroup = new ArrayList<JobQueue>(size);
		for (int i = 0; i < size; i++) {
			createJobQueue(i, null);
		}
	}

	public void setQueueTimeout(int index, int timeout) {
		if (index < 0 || index >= jobQueueGroup.size())
			return;
		jobQueueGroup.get(index).setTimeout(timeout);
	}

	public void resetAllQueue() {
		for (int i = 0; i < jobQueueGroup.size(); i++) {
			reset(i, false);
		}
	}

	public void run() {
		isRunning = true;
		long currentTime = 0;
		while (isRunning) {
			Utils.sleep(50);
			currentTime = System.currentTimeMillis();
			for (int i = 0; i < jobQueueGroup.size(); i++) {
				jobQueueGroup.get(i).peek(currentTime);
				if (jobQueueGroup.get(i).getQueueState() > JobQueueOB.JOB_QUEUE_BLOCK_STATE) {
					System.out.println("队列繁忙[" + i + "]:" + jobQueueGroup.get(i).getJobCount());
					reset(i, true);
				}
			}
		}
		for (int i = 0; i < jobQueueGroup.size(); i++) {
			if (jobQueueGroup.get(i) != null) {
				jobQueueGroup.get(i).stop();
			}
		}
		jobQueueGroup.clear();
	}

	public void addJob(int index, Runnable job) {
		if (index < 0 || index >= jobQueueGroup.size() || jobQueueGroup.get(index) == null)
			return;
		jobQueueGroup.get(index).addJob(job);
	}

	private void createJobQueue(int index, ConcurrentLinkedQueue<Runnable> jobs) {
		JobQueue jobQueue = new JobQueue(jobs);
		jobQueueGroup.add(jobQueue);
		jobQueue.start();
		logger.error("jobQueue init : " + System.currentTimeMillis() + " index=" + index);
	}

	public JobQueue getJobQueue(int index) {
		if (index < 0 || index >= jobQueueGroup.size())
			return null;
		return jobQueueGroup.get(index);
	}

	public void stop() {
		isRunning = false;
	}

	public void reset(int index, boolean isCopyingJob) {
		JobQueue jobQueue = jobQueueGroup.get(index);
		ConcurrentLinkedQueue<Runnable> jobs = jobQueue.getJobs();
		new Thread(new StopJobQueue(jobQueue)).start();
		if (isCopyingJob) {
			new Thread(new ResetJobQueue(index, jobs)).start();
		} else {
			new Thread(new ResetJobQueue(index, null)).start();
			jobs.clear();
		}
	}

	public void resetJobQueue(int index, ConcurrentLinkedQueue<Runnable> jobs) {
		createJobQueue(index, jobs);
	}

	private class StopJobQueue implements Runnable {
		private JobQueue jobQueue;

		public StopJobQueue(JobQueue jobQueue) {
			this.jobQueue = jobQueue;
		}

		public void run() {
			StackTraceElement[] stacks = jobQueue.getRunner().getStackTrace();
			for (int i = 0; i < stacks.length; i++) {
				System.out.println(stacks[i]);
			}
			jobQueue.stop();
		}
	}

	private class ResetJobQueue implements Runnable {
		private int index;
		private ConcurrentLinkedQueue<Runnable> jobs;

		public ResetJobQueue(int index, ConcurrentLinkedQueue<Runnable> jobs) {
			this.index = index;
			this.jobs = jobs;
		}

		public void run() {
			resetJobQueue(index, jobs);
		}
	}
}
